/*
 * bmpHandler.c
 *
 *  Created on: May 21, 2013
 *      Author: koldar
 */


#include "bmp-tools.h"
#include <limits.h>

static int __row_pixel__;


void setPixelInImage(Pimage img,int x,int y,RGB rgb){
	if (x>=0 && y>=0 && x<=img->width && y<=img->height){
		img->map[y][x].r=rgb.r;
		img->map[y][x].g=rgb.g;
		img->map[y][x].b=rgb.b;
	}
}

bool equalsRGB(RGB color1,RGB color2){
	return	color1.r==color2.r &&
			color1.g==color2.g &&
			color1.b==color2.b;
}

//TODO testing
void updatePixelInImage(Pimage img,int x,int y,RGB rgb){
	if (x>=0 && y>=0 && x<=img->width && y<=img->height){
		img->map[y][x].r=rgb.r;
		img->map[y][x].g=rgb.g;
		img->map[y][x].b=rgb.b;
	}
}

void writeHeaderInFile(FILE* f,int h,int w){

	int filesize = 54 + 3*w*h;  //w is your image width, h is image height, both int

	//INFO HEADER
	unsigned char bmpinfoheader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0};
	bmpinfoheader[ 4] = (unsigned char)(       w    );
	bmpinfoheader[ 5] = (unsigned char)(       w>> 8);
	bmpinfoheader[ 6] = (unsigned char)(       w>>16);
	bmpinfoheader[ 7] = (unsigned char)(       w>>24);
	bmpinfoheader[ 8] = (unsigned char)(       h    );
	bmpinfoheader[ 9] = (unsigned char)(       h>> 8);
	bmpinfoheader[10] = (unsigned char)(       h>>16);
	bmpinfoheader[11] = (unsigned char)(       h>>24);
	//FILE HEADER
	unsigned char bmpfileheader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0};
	bmpfileheader[ 2] = (unsigned char)(filesize    );
	bmpfileheader[ 3] = (unsigned char)(filesize>> 8);
	bmpfileheader[ 4] = (unsigned char)(filesize>>16);
	bmpfileheader[ 5] = (unsigned char)(filesize>>24);

	int i;
	for (i=0;i<14;i++){
		fprintf(f,"%c",bmpfileheader[i]);
	}
	for (i=0;i<40;i++){
			fprintf(f,"%c",bmpinfoheader[i]);
	}
	__row_pixel__=0;
}

Pimage initImage(int w,int h){
	Pimage img=malloc(sizeof(Pimage));
	checkMalloc(img,"bmpHandler.c:initImage:1");
	img->width=w;
	img->height=h;
	img->map=(RGB**)malloc(h*sizeof(RGB**));
	checkMalloc(img->map,"bmHandler.c:initImage:2");
	int i;
	for (i=0;i<h;i++){
		img->map[i]=(RGB*)malloc(w*sizeof(RGB));
		checkMalloc(img->map[i],"bmHandler.c:initImage:3");
	}
	return img;
}

//TODO testing
void freeImage(Pimage img){
	free(img->map);
	free(img);
}

RGB getRGB(unsigned char r,unsigned char g,unsigned char b){
	RGB result;
	result.r=r;
	result.g=g;
	result.b=b;
	return result;
}
//TODO testing
void printRGB(FILE* f,RGB rgb){
	printf("%d %d %d ",(int)rgb.r,(int)rgb.g,(int)rgb.b);
}

void writePixelInFile(FILE* f,RGB rgb){
	fprintf(f,"%c%c%c",rgb.b,rgb.g,rgb.r);
	__row_pixel__++;
}

void fillColor(Pimage img,RGB color){
	int y;
	int x;
	for (y=0;y<img->height;y++){
		for (x=0;x<img->width;x++){
			setPixelInImage(img,x,y,color);
		}
	}
}

void drawLine(Pimage img,int fromx,int fromy, int tox, int toy, int radius, RGB color){
	int x;
	int y;
	int minx=fromx,maxx=tox;
	int miny=fromy,maxy=toy;
	if ((fromx==tox)||(abs(tox-fromx)<=10)){ //linea verticale o quasi verticali
		validateMinMax(&miny,&maxy);
		x=tox;
		for (y=miny;y<maxy;y++){
			for (x=(fromx-2*radius);x<(fromx+2*radius);x++){
				updatePixelInImage(img,x,y,color);
			}
		}
		return;
	}
	if (fromy==toy){//linea orizzontale
		validateMinMax(&minx,&maxx);
		for (x=minx;x<maxx;x++){
			for (y=(fromy-2*radius);y<(fromy+2*radius);y++){
				updatePixelInImage(img,x,y,color);
			}
		}
		return;
	}
	//resto delle linee
	float m=(toy-fromy)/(tox-fromx+0.0);
	float q=-m*fromx+fromy;
	/*STAMPA M e Q
	printf("m=%f\n",m);
	printf("q=%f\n",q);*/
	validateMinMax(&minx,&maxx);
	for (x=minx;x<maxx;x++){
		for (y=-2*radius;y<+2*radius;y++){
			updatePixelInImage(img,x,((int)ceil(m*x+q+y)),color);
		}
	}
}

void applyImageToFile(Pimage img, FILE* bmpfile){

	int y;
	int x;
	int i;
	int pixelAdded;

	for (y=0;y<img->height;y++){
		pixelAdded=0;
		for (x=0;x<img->width;x++){
			writePixelInFile(bmpfile,img->map[img->height-y-1][x]);
			pixelAdded++;
		}
		//for (i=0;x<(4-(3*(pixelAdded%4)));i++){
		for (i=0;i<(4-(sizeof(RGB)*img->width)%4);i++){
			fprintf(bmpfile,"%c",0x00);
		}
	}
}


